using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace Splino.D3D
{
    /// <summary>
    /// A ListView designed for the Scene Manager that shows various objects properties
    /// and allows icons in ListViewSubItems
    /// </summary>
    public partial class SceneManagerListView : UserControl
    {
        int _minSmallColumnSize = 42;

        ListViewColumnSorter _columnSorter;

        /// <summary>
        /// Constructor
        /// </summary>
        public SceneManagerListView()
        {
            InitializeComponent();

            _columnSorter = new ListViewColumnSorter();
            _listView.ListViewItemSorter = _columnSorter;
        }

        /// <summary>ListView</summary>
        public ListView ListView { get { return _listView; } }

        /// <summary>ListView Items Collection</summary>
        public ListView.ListViewItemCollection Items { get { return _listView.Items; } }

        /// <summary>ListViewGroups Collection</summary>
        public ListViewGroupCollection Groups { get { return _listView.Groups; } }

        /// <summary>ListView Column Headers Collections</summary>
        public ListView.ColumnHeaderCollection Columns { get { return _listView.Columns; } }

        private void _listView_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == _columnSorter.ColumnToSort)
            {
                if (_columnSorter.SortOrder == SortOrder.Ascending)
                    _columnSorter.SortOrder = SortOrder.Descending;
                else
                    _columnSorter.SortOrder = SortOrder.Ascending;
            }
            else
            {
                _columnSorter.ColumnToSort = e.Column;
                _columnSorter.SortOrder = SortOrder.Ascending;
            }

            _listView.Sort();
        }

        private void _listView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            e.DrawDefault = true;
        }

        private void _listView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            if (e.SubItem.GetType() == typeof(ListViewImageSubItem))
            {
                ListViewImageSubItem imageSubItem = (ListViewImageSubItem)e.SubItem;
                if (imageSubItem.Checked)
                {
                    //e.Graphics.DrawImage(
                    e.Graphics.DrawImage(
                        imageSubItem.CheckedImage,
                        imageSubItem.Bounds.Location.X + 
                        (imageSubItem.Bounds.Width/2) -
                        (imageSubItem.CheckedImage.Width/2),
                        imageSubItem.Bounds.Location.Y,
                        imageSubItem.CheckedImage.Width,
                        imageSubItem.CheckedImage.Height);
                }
                else
                {
                    e.Graphics.DrawImage(
                        imageSubItem.UncheckedImage,
                        imageSubItem.Bounds.Location.X + 
                        (imageSubItem.Bounds.Width/2) - 
                        (imageSubItem.UncheckedImage.Width / 2),
                        imageSubItem.Bounds.Location.Y,
                        imageSubItem.UncheckedImage.Width,
                        imageSubItem.UncheckedImage.Height);
                }
            }
            else
                e.DrawDefault = true;
        }

        private void _listView_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            e.DrawDefault = true;
        }

        /// <summary>
        /// Creates a ListView item based on the properties of a Splino Object
        /// </summary>
        /// <param name="splinoObject">Splino Object to derive a ListviewItem from</param>
        /// <param name="isChildObject">True if the object belongs in the Child Objects
        /// group and false if it is selected node in the TreeView</param>
        public void AddListViewItem(SplinoObject splinoObject, bool isChildObject)
        {
            ListViewItem listViewItem = new ListViewItem();
            listViewItem.Text = splinoObject.Name;
            listViewItem.Name = splinoObject.Name;
            listViewItem.Tag = splinoObject;
            listViewItem.UseItemStyleForSubItems = false;

            if (isChildObject)
                listViewItem.Group = _listView.Groups[1];
            else
                listViewItem.Group = _listView.Groups[0];

            ListViewItem.ListViewSubItem typeSubItem = 
                new ListViewItem.ListViewSubItem(listViewItem, splinoObject.ObjectType);

            ListViewItem.ListViewSubItem colorSubItem =
                new ListViewItem.ListViewSubItem();
            colorSubItem.BackColor = splinoObject.Color;

            ListViewImageSubItem lockedSubItem = new ListViewImageSubItem();
            lockedSubItem.CheckedImage = SplinoImageList.Instance.Images["Locked"];
            lockedSubItem.UncheckedImage = SplinoImageList.Instance.Images["Unlocked"];
            lockedSubItem.Checked = splinoObject.Locked;

            ListViewImageSubItem visibleSubItem = new ListViewImageSubItem();
            visibleSubItem.CheckedImage = SplinoImageList.Instance.Images["Visible"];
            visibleSubItem.UncheckedImage = SplinoImageList.Instance.Images["Invisible"];
            visibleSubItem.Checked = !splinoObject.Hidden;

            ListViewItem.ListViewSubItemCollection subItems =
                new ListViewItem.ListViewSubItemCollection(listViewItem);
            subItems.Add(typeSubItem);
            subItems.Add(colorSubItem);
            subItems.Add(lockedSubItem);
            subItems.Add(visibleSubItem);

            lockedSubItem.Check += new ImageSubItemCheckEventHandler(SubItemCheck);
            lockedSubItem.Uncheck += new ImageSubItemUncheckEventHandler(SubItemCheck);
            visibleSubItem.Check += new ImageSubItemCheckEventHandler(SubItemCheck);
            visibleSubItem.Uncheck += new ImageSubItemUncheckEventHandler(SubItemCheck);

            _listView.Items.Add(listViewItem);
        }

        private void SubItemCheck(object sender, EventArgs e)
        {
            _listView.Invalidate();
        }

        /// <summary>
        /// Retrieves the ListViewItem associated with the given Splino Object.
        /// </summary>
        /// <param name="splinoObject">The Splino Object represented by the ListViewItem
        /// being searched for.</param>
        /// <returns>A ListViewItem representing the given Splino Object.</returns>
        public ListViewItem FindSplinoObjectsListViewItem(SplinoObject splinoObject)
        {
            foreach (ListViewItem listViewItem in _listView.Items)
                if (listViewItem.Tag == splinoObject)
                    return listViewItem;
            return null;
        }

        private void _listView_ColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
        {
            if (e.ColumnIndex > 1)
            {
                if (e.NewWidth < _minSmallColumnSize)
                {
                    e.Cancel = true;
                    e.NewWidth = _listView.Columns[e.ColumnIndex].Width;
                }
            }
        }

        private void _listView_MouseUp(object sender, MouseEventArgs e)
        {
            foreach (ListViewItem listViewItem in _listView.Items)
            {
                foreach (ListViewItem.ListViewSubItem listViewSubItem in listViewItem.SubItems)
                {
                    if (listViewSubItem.Bounds.Contains(e.X, e.Y))
                    {
                        SplinoObject splinoObject = (SplinoObject)listViewItem.Tag;
                        ListViewImageSubItem imageSubItem;

                        switch (listViewItem.SubItems.IndexOf(listViewSubItem))
                        {
                            case 2:
                                CommandManager.Instance.ExecuteCommand(
                                    new Commands.Color(new SplinoObject[] { splinoObject }));
                                break;
                            case 3:
                                imageSubItem = (ListViewImageSubItem)listViewSubItem;
                                if (splinoObject.Locked)
                                {
                                    CommandManager.Instance.ExecuteCommand(
                                        new Commands.Unlock(new SplinoObject[] { splinoObject }));
                                    imageSubItem.Checked = false;
                                }
                                else
                                {
                                    CommandManager.Instance.ExecuteCommand(
                                        new Commands.Lock(new SplinoObject[] {splinoObject}));
                                    imageSubItem.Checked = true;
                                } 
                                break;

                            case 4:
                                imageSubItem = (ListViewImageSubItem)listViewSubItem;
                                if (splinoObject.Hidden)
                                {
                                    CommandManager.Instance.ExecuteCommand(
                                        new Commands.Show(new SplinoObject[] { splinoObject }));
                                    imageSubItem.Checked = true;
                                }
                                else
                                {
                                    CommandManager.Instance.ExecuteCommand(
                                        new Commands.Hide(new SplinoObject[] { splinoObject }));
                                    imageSubItem.Checked = false;
                                }
                                break;
                        }
                    }
                }
            }
        }

        private void _listView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            SplinoObject splinoObject = (SplinoObject)e.Item.Tag;
            if (e.IsSelected)
            {
                if (!splinoObject.Selected)
                    CommandManager.Instance.ExecuteCommand(
                        new Commands.Select_System(new SplinoObject[] { splinoObject }));
            }
            else
                if (splinoObject.Selected)
                    splinoObject.Deselect();
        }
    }

    /// <summary>
    /// A ListViewSubItem that draws an image instead of simply displaying text
    /// </summary>
    public class ListViewImageSubItem : ListViewItem.ListViewSubItem
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public ListViewImageSubItem() : base() { }

        Image _checkedImage;
        /// <summary>
        /// The image to draw when the subitem is checked/on.
        /// </summary>
        public Image CheckedImage
        {
            get { return _checkedImage; }
            set { _checkedImage = value; }
        }

        Image _uncheckedImage;
        /// <summary>
        /// The image to draw when the subitem is unchecked/off.
        /// </summary>
        public Image UncheckedImage
        {
            get { return _uncheckedImage; }
            set { _uncheckedImage = value; }
        }

        bool _checked = false;
        /// <summary>
        /// Gets or sets if the sub items is checked/on.
        /// </summary>
        public bool Checked
        {
            get { return _checked; }
            set 
            { 
                _checked = value;
                if (value)
                {
                    if (Check != null)
                        Check(this, new EventArgs());
                }
                else
                {
                    if (Uncheck != null)
                        Uncheck(this, new EventArgs());
                }
            }
        }
        
        /// <summary>
        /// Event raised when the ListViewImageSubItem is checked.
        /// </summary>
        public event ImageSubItemCheckEventHandler Check;

        /// <summary>
        /// Event raised when the ListViewImageSubItem is unchecked.
        /// </summary>
        public event ImageSubItemUncheckEventHandler Uncheck;
    }

    /// <summary>
    /// Event handler delegate for a ListViewImageSubItem Check event.
    /// </summary>
    /// <param name="sender">The ListViewImageSubItem.</param>
    /// <param name="e">Event arguments.</param>
    public delegate void ImageSubItemCheckEventHandler(object sender, EventArgs e);

    /// <summary>
    /// Event handler delegate for a ListViewImageSubItem Uncheck event.
    /// </summary>
    /// <param name="sender">The ListViewImageSubItem</param>
    /// <param name="e">Event arguments.</param>
    public delegate void ImageSubItemUncheckEventHandler(object sender, EventArgs e);
}
